from inspect import isfunction, getmembers

from apscheduler.jobstores.base import JobLookupError
from django_apscheduler.models import DjangoJobExecution
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import status
from rest_framework.filters import SearchFilter

from rest_framework.generics import ListCreateAPIView, ListAPIView, UpdateAPIView, DestroyAPIView
from rest_framework.response import Response

from timing.serializer import JobsListSerializer, JobCreateSerializer, JobFunctionsSerializer, JobUpdateSerializer, \
    JobExecutionsSerializer
from timing.jobs.run import scheduler
from timing.jobs import tasks
from utils.page import Mypage


class JobsListCreateAPIView(ListCreateAPIView):
    """
    get:
    任务调度--任务列表
    post:
    任务调度--新增
    """
    filter_backends = (SearchFilter,)
    search_fields = ('name', 'desc')
    pagination_class = Mypage


    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            res = self.get_paginated_response(serializer.data)
            return Response(data={'data': res.data})
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    def filter_queryset(self, queryset):       # 过滤
        search_params = self.request.query_params.get('search')
        if search_params:
            obj_list = list()
            for obj in queryset:
                doc = tasks.__dict__.get(obj.name).__doc__
                if search_params in obj.name or search_params in doc:
                    obj_list.append(obj)
            return obj_list
        else:
            return queryset

    def get_queryset(self):
        return scheduler.get_jobs()       # 拿到所有任务列表

    def get_serializer_class(self):
        if self.request.method.lower() == 'get':
            return JobsListSerializer
        else:
            return JobCreateSerializer


class JobFunctionsListAPIView(ListAPIView):
    """
    get:
    任务调度--任务调度函数列表

    获取任务调度函数列表, status: 200(成功), return: 任务调度函数列表
    """
    serializer_class = JobFunctionsSerializer
    filter_backends = (SearchFilter,)
    search_fields = ('name', 'desc')
    pagination_class = Mypage

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            res = self.get_paginated_response(serializer.data)
            return Response(data={'data': res.data})
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    def get_queryset(self):
        return list(filter(None, [obj if isfunction(obj[1]) and obj[0] != 'single_task' else None for obj in
                                  getmembers(tasks)]))

    def filter_queryset(self, queryset):
        search_params = self.request.query_params.get('search')
        if search_params:
            obj_list = list()
            for obj in queryset:
                doc = '' if obj[1].__doc__ is None else obj[1].__doc__
                if search_params in obj[0] or search_params in doc:
                    obj_list.append(obj)
            return obj_list
        else:
            return queryset


class JobUpdateDestroyAPIView(UpdateAPIView, DestroyAPIView):
    serializer_class = JobUpdateSerializer

    def get_queryset(self):
        return scheduler.get_jobs()

    def get_job_id(self):
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
        return self.kwargs[lookup_url_kwarg]


    def put(self, request, *args, **kwargs):
        job = scheduler.get_job(self.get_job_id())
        if not job:
            return Response(data={'detail': '调度任务不存在'}, status=status.HTTP_400_BAD_REQUEST)
        serializer = self.get_serializer(job, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(data=serializer.data, status=status.HTTP_200_OK)

    def delete(self, request, *args, **kwargs):
        try:
            scheduler.remove_job(self.get_job_id())
        except JobLookupError:
            return Response(data={'detail': '调度任务不存在'}, status=status.HTTP_400_BAD_REQUEST)
        return Response(status=status.HTTP_204_NO_CONTENT)


class JobExecutionsListAPIView(ListAPIView):
    """
    查看调度记录
    """
    serializer_class = JobExecutionsSerializer
    queryset = DjangoJobExecution.objects.all()
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ['job__id']